/*******************************************************************/
/* @ All Rights Reserved Copyright (C) 2014 broada,Co.,Ltd.        */
/*                                                                 */
/*  NAME      = frssl_decode.c                                     */
/*  NOTE      =                                                    */
/*  DATE      = 2016/01/26 by guojq                                */
/*******************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "frcomm.h"
#include "frmem.h"
#include "frdssl.h"
#include "frssl_task_do.h"
#include "frssl_decode.h"

/* IP Header */
typedef struct IpHdr {
    char   ver_hl;              /* version/header length */
    char   tos;                 /* type of service */
    short  length;              /* total length */
    short  id;                  /* identification */
    short  offset;              /* fragment offset field */
    char   ttl;                 /* time to live */
    char   protocol;            /* protocol */
    short  sum;                 /* checksum */
    unsigned int src;           /* source address */
    unsigned int dst;           /* destination address */
} IpHdr;

/* TCP Header */
typedef struct TcpHdr {
    short  srcPort;            /* source port */
    short  dstPort;            /* destination port */
    unsigned int sequence;     /* sequence number */
    unsigned int ack;          /* acknoledgment number */
    char   offset;             /* data offset, reserved */
    char   flags;              /* option flags */
    short  window;             /* window */
    short  sum;                /* checksum */
    short  urgent;             /* urgent pointer */
} TcpHdr;

#define IP_V(ip)       ( ((ip)->ver_hl) >> 4)
#define IP_HL(ip)      ( (((ip)->ver_hl) & 0x0f) * 4)
#define TCP_FIN 0x01
#define TCP_SYN 0x02
#define TCP_RST 0x04
#define TCP_ACK 0x10

/*******************************************************************************
*  FUNC     :  根据pcap数据包头内容，做成ip头数据
*  ARGS     :  p_data(数据包内容)
*           :  p_st_info(ip头内容)
*           :  p_i_type(数据包类型[syn、fin、data])
*  RTN      :  FR_SUCC (success)
*           :  FR_FAIL (failed)
*  NOTE     :
*******************************************************************************/
int frssl_getipinfo(const unsigned char *p_data, sniffer_ipinfo *p_st_info, int *p_i_type)
{
    IpHdr *p_st_iphead;
    TcpHdr *p_st_tcp;
    
    if (p_data == NULL || p_st_info == NULL || p_i_type == NULL)
        return FR_FAIL;
    
    p_st_iphead = (IpHdr*)p_data;
    //必须为IPV4
    if (IP_V(p_st_iphead) != 4)
        return FR_FAIL;
    
    p_st_info->i_sip = p_st_iphead->src;
    p_st_info->i_dip = p_st_iphead->dst;
    
    p_st_tcp = (TcpHdr*)(p_data + IP_HL(p_st_iphead));
    p_st_info->i_sport = ntohs(p_st_tcp->srcPort);
    p_st_info->i_dport = ntohs(p_st_tcp->dstPort);
    
    if (p_st_tcp->flags & TCP_SYN && !(p_st_tcp->flags & TCP_ACK))
        *p_i_type = SSL_TYPE_SYN;
    else if ((p_st_tcp->flags & TCP_FIN || p_st_tcp->flags & TCP_RST) && (p_st_tcp->flags & TCP_ACK))
        *p_i_type = SSL_TYPE_FIN;
    else
        *p_i_type = SSL_TYPE_DATA;
    
    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  根据ip头数据和解密数据，做成传输的数据块
*  ARGS     :  p_data(解密后内容)
*           :  i_date_len(解密后内容的长度)
*           :  i_type(数据类型[syn、fin、data])
*           :  p_st_info(ip头信息])
*           :  pp_st_decode(传输用的数据块内容)
*  RTN      :  FR_SUCC (success)
*           :  FR_FAIL (failed)
*  NOTE     :
*******************************************************************************/
int frssl_mk_decode(unsigned char *p_data, int i_date_len, int i_type
                  , sniffer_ipinfo *p_st_info, struct timeval *p_st_ts
                  , ssl_decode **pp_st_decode)
{
    ssl_decode *p_st_decode = NULL;
    ssl_option *p_st_option = NULL;
    
    if (p_st_info == NULL || p_st_ts == NULL || pp_st_decode == NULL)
        return FR_FAIL;
    
    p_st_decode = (ssl_decode *)frmalloc(sizeof(ssl_decode) + i_date_len);
    if (p_st_decode == NULL)
        return FR_FAIL;
    
    p_st_option = &p_st_decode->st_option;
    
    p_st_option->i_version = SSL_VERSION;
    memcpy(&p_st_option->st_ipinfo, p_st_info, sizeof(sniffer_ipinfo));
    memcpy(&p_st_option->st_ts, p_st_ts, sizeof(struct timeval));
    p_st_option->i_conn_type = i_type;
    
    if (p_data && i_date_len > 0)
    {
        p_st_decode->i_decode_len = i_date_len;
        memcpy(p_st_decode->p_decode, p_data, i_date_len);
    }
    else
        p_st_decode->i_decode_len = 0;
        
    *pp_st_decode = p_st_decode;
    
    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  把需要解密的数据保存起来
*  ARGS     :  p_data(解密后内容)
*           :  i_date_len(解密后内容的长度)
*           :  i_type(数据类型[syn、fin、data])
*           :  p_st_info(ip头信息])
*           :  pp_st_encode(需要解密的数据)
*  RTN      :  FR_SUCC (success)
*           :  FR_FAIL (failed)
*  NOTE     :
*******************************************************************************/
int frssl_mk_encode_lst(unsigned char *p_data, int i_date_len, int i_type
                  , sniffer_ipinfo *p_st_info, struct timeval *p_st_ts
                  , Frssl_thread **pp_st_encode)
{
    Frssl_thread *p_st_encode = NULL;
    ssl_option *p_st_option = NULL;
    
    if (p_st_info == NULL || p_st_ts == NULL || pp_st_encode == NULL)
        return FR_FAIL;
    
    p_st_encode = (Frssl_thread *)frmalloc(sizeof(Frssl_thread));
    if (p_st_encode == NULL)
        return FR_FAIL;
    
    p_st_option = &p_st_encode->st_option;
    
    p_st_option->i_version = SSL_VERSION;
    memcpy(&p_st_option->st_ipinfo, p_st_info, sizeof(sniffer_ipinfo));
    memcpy(&p_st_option->st_ts, p_st_ts, sizeof(struct timeval));
    p_st_option->i_conn_type = i_type;
    
    if (p_data && i_date_len > 0)
    {
        p_st_encode->i_encode_len = i_date_len;
        p_st_encode->p_encode = (char *)frmalloc(i_date_len);
        if (p_st_encode->p_encode == NULL)
        {
            frfree(p_st_encode);
            return FR_FAIL;
        }
        memcpy(p_st_encode->p_encode, p_data, i_date_len);
    }
    else
        p_st_encode->i_encode_len = 0;
        
    *pp_st_encode = p_st_encode;
    
    return FR_SUCC;
}
